package com.eugeneMa.config;
import com.alibaba.fastjson.JSON;
import org.apache.log4j.Logger;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * webSocket服务
 *
 * @author Eugenema
 * @date 2022/5/8 13:47
 */

@ServerEndpoint("/websocket/testsocket")
@Component
public class WebSocketServer {
    private static Logger logger = Logger.getLogger(WebSocketServer.class);

    /** 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的 */
    private static AtomicInteger onlineCount = new AtomicInteger(0);
    /** concurrent包的线程安全Set，用来存放每个客户端对应的WebSocket对象 */
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();

    /** 与某个客户端的连接会话，需要通过它来给客户端发送数据 */
    private Session session;


    /**
     * 连接建立成功，调用的方法
     *
     * @author Eugenema
     * @date 2022/5/8 14:39
     *
     **/
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        //记录该客户端的webSocket
        webSocketSet.add(this);
        //记录在线数
        int onlineNum = WebSocketServer.onlineCount.addAndGet(1);
        logger.info("有新窗口开始监听,当前在线人数为：" + onlineNum);
        try {
            sendMessage(onlineNum);
        } catch (Exception e) {
            logger.error("websocket IO异常", e);
        }
    }

    /**
     * 连接关闭调用的方法
     *
     * @author Eugenema
     * @date 2022/5/8 14:57
     **/
    @OnClose
    public void onClose(Session session) {
        try {
            //删除该客户端的webSocket
            webSocketSet.remove(this);
            //刷新在线人数
            int onlineNum = WebSocketServer.onlineCount.addAndGet(-1);
            //关闭会话
            session.close();
            logger.info("连接关闭！当前在线人数为：" + onlineNum);
        } catch (IOException e) {
            logger.error("连接关闭方法异常！", e);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @author Eugenema
     * @date 2022/5/8 14:58
     *
     * @param message 客户端发送过来的消息
     **/
    @OnMessage
    public void onMessage(String message, Session session) {
        //发送当前服务器人数发送
        sendMessage(onlineCount.get());
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("webSocketServer发生错误");
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     *
     * @author Eugenema
     * @date 2022/5/8 14:51
     *
     * @param message 要发送的信息
     **/
    public void sendMessage(Object message)  {
        /** 发送的信息 */
        String jsonMessage = JSON.toJSONString(message);
        try {
            synchronized (this.session) {
                this.session.getBasicRemote().sendText(jsonMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("WebSocketServer发送信息失败！");
        }
    }

    /**
     * 群发自定义消息
     *
     * @author Eugenema
     * @date 2022/5/8 15:01
     *
     * @param obj 要发送的信息
     **/
    public static void sendInfo(Object obj) {
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(obj);
            } catch (Exception e) {
                logger.error("发送消息异常，跳入下一个！");
                continue;
            }
        }
    }
}
